Part 1: 모바일 보안 아키텍처
| 항목 | 내용 |
|---|---|
| 문서명 | Part 1: 모바일 보안 아키텍처 (Mobile Security Architecture) |
| 제품명 | DTA Wide Sleep Management Platform |
| 작성일 | 2026-02-10 |
| 적용범위 | Part 1 (모바일 앱) |
1. 모바일 보안 개요
목표: 디바이스 레벨에서 민감 데이터 보호, 안전한 통신, 악의적 행위 탐지
적용 플랫폼:
- iOS 18.0+ (Swift, SwiftUI, Tuist 빌드 시스템)
- Android: [TODO: Android 구현 예정]
2. 민감 데이터 저장 정책
2.1 저장소 유형 및 보안 통제
| 데이터 유형 | iOS 저장소 | Android 저장소 | 암호화 방식 | 접근 통제 |
|---|---|---|---|---|
| 인증 토큰 (JWT) | Keychain | [TODO: Android 구현 예정] | iOS: Keychain 하드웨어 암호화 | kSecAttrAccessibleAfterFirstUnlock |
| 비밀번호 (로컬 캐시) | Keychain | [TODO: Android 구현 예정] | iOS: Keychain 하드웨어 암호화 | 동일 |
| PIN 코드 해시 | Keychain | [TODO: Android 구현 예정] | iOS: SHA256 해시 후 Keychain 저장 | 동일 |
| 수면 로그 (앱 데이터) | Core Data (WideDataModel.sqlite) | [TODO: Android 구현 예정] | iOS 기본 File Protection [TODO: 명시적 설정 필요] | 앱 전용 |
| 설문 응답 (앱 데이터) | Core Data | [TODO: Android 구현 예정] | iOS 기본 File Protection [TODO: 명시적 설정 필요] | 앱 전용 |
| 사용자 설정 (비민감) | UserDefaults | [TODO: Android 구현 예정] | 없음 | 앱 전용 (Device UUID 캐시만) |
| 캐시 데이터 | NSCache (메모리) | [TODO: Android 구현 예정] | 없음 | 앱 전용, 메모리 내 (countLimit: 100) |
2.2 Keychain/Keystore 구현
Keychain 저장 데이터:
- 인증 토큰 (
LiveSleepQDENetworkManager+AppToken+KeyChain.swift) - 로그인 자격증명 (
LiveAuthManager+UserLoginCredential.swift) - PIN 코드 해시 (
LiveAuthManager+UserPINCode.swift) - Device UUID (
Config.swift)
Android Keystore:
[TODO: Android 구현 예정]
Android Keystore 구현은 Android 앱 개발 시 추가 예정
- Android Keystore (AES-256-GCM, StrongBox)
- EncryptedSharedPreferences
- 예상 구현: Kotlin + AndroidX Security
2.3 암호화 준수 매핑 (O.Cryp_2~5)
iOS 암호화 레이어 아키텍처:
3. 로컬 캐시 및 로그 정책
3.1 캐시 정책
| 캐시 유형 | 보관 기간 | 암호화 | 자동 삭제 조건 |
|---|---|---|---|
| API 응답 캐시 | 1시간 | ❌ 없음 (민감 데이터 제외) | 앱 종료, 메모리 부족 |
| 이미지 캐시 | 7일 | ❌ 없음 | LRU 알고리즘 |
| 로그인 세션 | 30일 | ✅ Keychain/Keystore | 로그아웃, 토큰 만료 |
민감 데이터 캐싱 금지:
- 비밀번호 (절대 캐싱 금지)
- 의료 데이터 원본 (API 응답에서 즉시 파싱 후 폐기)
- 다른 사용자 정보
3.2 로그 정책
프로덕션 빌드:
- 로그 레벨: ERROR 이상만 (WARN, INFO, DEBUG 비활성화)
- 민감 정보 자동 마스킹 (이메일, 토큰)
- Crash 리포트: Firebase Crashlytics (프로덕션 크래시 리포팅)
디버그 빌드:
- 로그 레벨: DEBUG 이상 전체
- 네트워크 요청/응답 로깅 (개발자 도구)
- 민감 정보 마스킹 유지
로그 저장 위치:
- iOS: Xcode Console (메모리 내, 디바이스 미저장)
- Android: Logcat (메모리 내, 디바이스 미저장)
4. 화면 보호 (Screen Protection)
[TODO: 미구현] 스크린샷 차단 및 백그라운드 블러
현재 상태: 사용자 발의 스크린샷 버튼(
ScreenshotButton.swift)만 존재하며, 시스템 수준 스크린샷 차단이나 앱 전환 시 블러 처리는 구현되어 있지 않음.향후 구현 필요:
- iOS:
UIApplication.userDidTakeScreenshotNotification감지 및 경고 표시- iOS:
UIApplication.willResignActiveNotification에서UIBlurEffect적용- Android:
FLAG_SECURE설정 (Android 구현 시)
5. 세션 및 토큰 처리
5.1 토큰 관리
AppToken + UserToken 이중 인증 (RS256 비대칭 서명):
| 토큰 유형 | 유효 기간 | 저장 위치 | 갱신 |
|---|---|---|---|
| AppToken (Access) | 30분 | Keychain (iOS) | 401 시 자동 갱신 |
| AppToken (Refresh) | 14일 | Keychain (iOS) | Access Token 만료 시 |
토큰 갱신 메커니즘 (실제 구현 - +UrlSession+Run.swift):
- 401 응답 시 자동 갱신 시도
- Exponential Backoff (max 5 retries)
- 갱신 실패 시 로그아웃 처리
로그아웃 시 삭제 항목 (LiveAuthRepository+Logout.swift):
- CoreData 전체 초기화
- Keychain 토큰 삭제
- 인증 상태 초기화
- PIN 코드 삭제
- Context 초기화
5.2 자동 로그아웃 정책
| 조건 | iOS 동작 | 서버 동작 | 사용자 알림 |
|---|---|---|---|
| Refresh Token 만료 (14일) | 자동 로그아웃 | 토큰 만료 처리 | 세션 만료 알림 |
| 토큰 갱신 5회 실패 | 자동 로그아웃 | - | 재로그인 요청 |
| 앱 미사용 (4시간) | Pin 비밀번호 입력 | - | 재인증 요청 |
[TODO: O.Auth_8] 앱 백그라운드 복귀 시 타이머 기반 재인증 구현 필요 (BSI O.Auth_8)
[TODO: O.Auth_9] 서버 측 비활성 감지 및 최대 활성 세션 시간 제한 구현 필요 (BSI O.Auth_9)
5.3 defer 패턴 기반 예외 처리 정책
defer 블록 실행 흐름 (정상/예외 모두 민감 데이터 해제):
구현 현황:
| 보호 방식 | 구현 상태 | 비고 |
|---|---|---|
| nil 처리 (메모리 해제) | ✅ 구현됨 | defer 블록 내 nil 할당 |
6. 디버그/릴리즈 보안 통제 분리
6.1 빌드 구성 차이
| 보안 통제 | 릴리즈 빌드 | 디버그 빌드 | 이유 |
|---|---|---|---|
| Jailbreak Detection | ✅ 활성화 (exit(0) 즉시 종료) | ❌ 비활성화 | 개발 환경 탈옥 디바이스 사용 |
| Symbol Stripping | ✅ STRIP_STYLE=non-global, dSYM 분리 | ❌ 비활성화 | 디버깅 편의 |
| 로그 레벨 | ERROR 이상 | DEBUG 이상 | 개발 중 디버깅 |
| API 엔드포인트 | 프로덕션 | 스테이징 | 테스트 환경 분리 |
| RSA 공개키 | prod 전용 키 | dev/stage 전용 키 | 환경별 키 분리 (Project.swift) |
| Firebase Crashlytics | ✅ 활성화 | ✅ 활성화 | 크래시 리포팅 |
디버그 빌드 배포 제한:
- App Store 배포 불가
- 내부 테스트용도
- TestFlight만 사용 (Android 미구현)
디버그 빌드 식별 (AppDelegate.swift):
#if DEBUG조건부 컴파일로 분리- 앱 카테고리:
.appCategoryMedical(Project.swift:53)
7. 모바일 인증 플로우
8. 루팅/탈옥 탐지 (Release Build Only)
8.1 iOS Jailbreak Detection (실제 구현 - JailBreakDetector.swift)
3가지 탐지 방법:
| 탐지 방법 | 함수명 | 검사 내용 |
|---|---|---|
| 1. 의심 파일 탐지 | checkSuspiciousFiles() | Cydia, Sileo, Zebra 등 26개+ 의심 경로 확인 |
| 2. Sandbox 위반 | checkSandboxViolation() | /private 디렉토리 파일 쓰기 시도 |
| 3. DYLD 검사 | checkDYLD() | 동적 라이브러리 injection 탐지 |
탐지 시 동작:
exit(0)즉시 종료- RELEASE 빌드에서만 실행 (
#if !DEBUG조건부 컴파일)
빌드별 동작:
| 빌드 | 탈옥 탐지 | 탐지 시 동작 |
|---|---|---|
| RELEASE | ✅ 활성화 | exit(0) 즉시 종료 |
| DEBUG | ❌ 비활성화 | 동작 없음 |
8.2 Android Root Detection
[TODO: Android 구현 예정]
Android 앱 개발 시 Root Detection 구현 필요
- 예상 라이브러리: RootBeer 또는 자체 구현
- 검사 항목:
su바이너리, Magisk,/system쓰기 가능 여부- 탐지 시 동작: iOS와 동일하게 즉시 종료 예정
9. 네트워크 요청 보안
9.1 HTTPS 강제 (App Transport Security)
iOS ATS 설정:
iOS 기본 ATS 정책을 사용. iOS 기본값으로 모든 HTTP 연결이 차단되며 HTTPS만 허용됨.
iOS URLSession 설정 (실제 구현 - Ext+URLSessionConfiguration.swift):
// 캐시 정책: 항상 서버에서 새로 요청
configuration.requestCachePolicy = .reloadIgnoringLocalCacheData
// 타임아웃 설정
configuration.timeoutIntervalForRequest = 30 // 요청 타임아웃: 30초
configuration.timeoutIntervalForResource = 60 // 리소스 타임아웃: 60초
Android Network Security Config:
[TODO: Android 구현 예정] Android 구현 시
network_security_config.xml에cleartextTrafficPermitted="false"설정 필요
9.2 API 요청 헤더
필수 헤더:
Authorization: Bearer {appToken}
Content-Type: application/json
Accept: application/json
10. 입력 검증 정책
10.1 iOS 클라이언트 입력 검증
Validator.swift 기반 검증 항목:
| 입력 유형 | 검증 규칙 | 구현 파일 |
|---|---|---|
| 이메일 | RFC 5322 형식 검증 | Validator.swift |
| 비밀번호 | 최소 길이, 복잡도 규칙 | Validator.swift |
| PIN 코드 | 숫자 4~6자리 | Validator.swift |
| 수면 시간 | 범위 검증 (0~24시간) | Validator.swift |
| 딥링크 파라미터 | URL 파라미터 검증 | TBD |
| 서버 응답 타입 | Decodable 기반 타입 검증 | 각 API Response 모델 |
11. 알림 보안 정책
11.1 로컬 알림 콘텐츠 현황
구현 파일: LocalPushNotificationType.swift
| 알림 유형 | 제목 | 민감 데이터 포함 |
|---|---|---|
| targetLOT (취침 1시간 전) | "Noch 1 Stunde bis zur Schlafenszeit" | ✅ 없음 |
| targetAET (기상 시간) | "Es ist Zeit aufzustehen!" | ✅ 없음 |
11.3 알림 권한 기본값 및 흐름 (O.Plat_5)
구현 파일: LiveNotificationManager+State.swift
알림 권한 기본값 분석 (O.Plat_5):
| 항목 | 상태 | 비고 |
|---|---|---|
| 초기 권한 상태 | notDetermined (미설정) | O.Plat_5 준수: 기본 비활성 ✅ |
| Provisional 알림 (무음 사전 알림) | 미사용 | 사용자 명시적 선택만 사용 |
| 권한 요청 시점 | 명시적 사용자 플로우 내 | 앱 시작 시 자동 요청 없음 |
| FCM 토큰 전송 | 권한 취득 후에만 | 미취득 시 FCM 토큰 미전송 |
11.4 원격 알림 보안 현황 및 갭
구현 파일: AppDelegate.swift, 백엔드 firebase-push.service.ts
| 항목 | 비고 |
|---|---|
| FCM 토큰 관리 (기기 토큰만 전송) | 민감 데이터 미포함 |
증빙 및 참조(Artifacts)
- Keychain 구현 코드 -
WLCore/Sources/KeyChain/KeyChainWrapper.swift - Jailbreak Detection 코드 -
WLCore/Sources/JailBreak/JailBreakDetector.swift - 암호화 유틸리티 -
WLCore/Sources/Crypto/CryptoHelper.swift(SHA256, RSA-2048) - 네트워크 설정 -
Ext+URLSessionConfiguration.swift(캐시, 타임아웃) - 토큰 관리 -
LiveSleepQDENetworkManager+AppToken+KeyChain.swift - 로그아웃 처리 -
LiveAuthRepository+Logout.swift(전체 데이터 삭제) - 빌드 설정 -
Ext+Project.swift(Symbol Stripping),Project.swift(환경별 RSA 키) - 인증 플로우 다이어그램 - 본 문서 Section 7
- Firebase 설정 -
GoogleService-Info-prod.plist(Analytics 비활성화) - MobSF 보고서 - [TODO: 정적 분석 실행 필요]
| 규정 | 요구사항 | 구현 | 상태 | 증거 |
|---|---|---|---|---|
| BSI TR-03161 Part 1 | 민감 데이터 로컬 암호화 | Keychain (kSecAttrAccessibleAfterFirstUnlock) | ✅ 구현됨 | KeyChainWrapper.swift |
| BSI TR-03161 Part 1 | 안전한 네트워크 통신 | TLS (iOS 기본 ATS) | ✅ 구현 | Ext+URLSessionConfiguration.swift |
| BSI TR-03161 Part 1 | 디바이스 무결성 검증 | Jailbreak Detection (3가지 탐지, exit(0)) | ✅ 구현됨 (iOS) | JailBreakDetector.swift |
| GDPR Article 32 | 적절한 기술적 조치 | 전체 보안 통제 | ✅ 구현됨 | 본 문서 |
| OWASP MASVS | 강화된 모바일 보안 | 탈옥 탐지, 토큰 보안 | ⚠️ 부분 | MobSF 보고서 [TODO: 실행 필요] |